home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / p4 / p4-1_2a.lha / p4-1.2a / lib / p4_MD.c < prev    next >
C/C++ Source or Header  |  1992-12-15  |  28KB  |  1,103 lines

  1. #include "p4.h"
  2. #include "p4_sys.h"
  3.  
  4. /* --------- Most Machine Dependent Stuff is in this file */
  5.  
  6. #if defined(ALLIANT) && defined(USE_XX_SHMALLOC)
  7. char *xx_shmalloc();
  8. P4VOID xx_shfree();
  9. P4VOID xx_init_shmalloc();
  10. #endif
  11.  
  12. #if defined(KSR) && defined(USE_XX_SHMALLOC)
  13. char *xx_shmalloc();
  14. P4VOID xx_shfree();
  15. P4VOID xx_init_shmalloc();
  16. #endif
  17.  
  18. P4VOID MD_initmem(memsize)
  19. int memsize;
  20. {
  21. #ifdef TC_2000
  22.     MD_malloc_hint(HEAP_INTERLEAVED | HEAP_UNCACHED, 0);
  23. #endif
  24.  
  25. #if defined(GP_1000)
  26.     xx_malloc(0, memsize);
  27. #endif
  28.  
  29. #if defined(KSR) && defined(USE_XX_SHMALLOC)
  30. #define  UNMAPPED  (caddr_t) -1
  31.     caddr_t memory;
  32.     unsigned size = ((memsize + 4095) / 4096) * 4096;
  33.  
  34.     /*   create shared memory  */
  35.     memory = (char *) mmap( NULL, memsize, PROT_READ | PROT_WRITE,
  36.                                MAP_ANONYMOUS | MAP_VARIABLE |MAP_SHARED,
  37.                                -1,0);
  38.     if ( memory == UNMAPPED)
  39.     {
  40.         p4_error("OOPS: mmap failed\n",memory);
  41.     }
  42.     xx_init_shmalloc(memory, size);
  43. #endif
  44.  
  45. #if defined(ALLIANT) && !defined(USE_XX_SHMALLOC)
  46.     xx_malloc(0, memsize);
  47. #endif
  48.  
  49. #if defined(ALLIANT) && defined(USE_XX_SHMALLOC)
  50.     unsigned size = ((memsize + 4095) / 4096) * 4096;
  51.     char *memory = valloc(size);
  52.     long id;
  53.     if (!memory)
  54.     p4_error("MD_initmem: failed in valloc", size);
  55.  
  56.     id = (long) getpid();    /* get a unique id */
  57.     if (create_shared_region(id, (char *) memory, size, 0))
  58.     p4_error("MD_init_mem: failed in create_shared_region", size);
  59.     xx_init_shmalloc(memory, size);
  60. #endif
  61.  
  62. #if defined(SYSV_IPC) && defined(USE_XX_SHMALLOC)
  63.     int i,nsegs;
  64.     unsigned size, segsize = P4_SYSV_SHM_SEGSIZE;
  65.     char *mem, *tmem, *pmem;
  66.  
  67.     if (memsize  &&  (memsize % P4_SYSV_SHM_SEGSIZE) == 0)
  68.     nsegs = memsize / segsize;
  69.     else
  70.     nsegs = memsize / segsize + 1;
  71.     size = nsegs * segsize;
  72.     if ((sysv_shmid[0] = shmget(getpid(),segsize,IPC_CREAT|0600)) == -1)
  73.     {
  74.     p4_error("OOPS: shmget failed\n",sysv_shmid[0]);
  75.     }
  76.     if ((mem = (char *)shmat(sysv_shmid[0],NULL,0)) == (char *)-1)
  77.     {
  78.     p4_error("OOPS: shmat failed\n",mem);
  79.     }
  80.     sysv_num_shmids++;
  81.     nsegs--;
  82.     pmem = mem;
  83.     for (i=1; i <= nsegs; i++)
  84.     {
  85.     if ((sysv_shmid[i] = shmget(i+getpid(),segsize,IPC_CREAT|0600)) == -1)
  86.     {
  87.         p4_error("OOPS: shmget failed\n",sysv_shmid[i]);
  88.     }
  89.         if ((tmem = (char *)shmat(sysv_shmid[i],pmem+segsize,0)) == (char *)-1)
  90.         {
  91.             if ((tmem = (char *)shmat(sysv_shmid[i],pmem-segsize,0)) == (char *)-1)
  92.             {
  93.                 p4_error("OOPS: shmat failed\n",tmem);
  94.             }
  95.         else
  96.         {
  97.         mem = tmem;
  98.         }
  99.         }
  100.     sysv_num_shmids++;
  101.     pmem = tmem;
  102.     }
  103.     xx_init_shmalloc(mem,size);
  104. #endif
  105.  
  106. #if defined(MULTIMAX)
  107.     share_malloc_init(memsize);
  108. #endif
  109. }
  110.  
  111. P4VOID MD_initenv()
  112. {
  113.  
  114.     /* next 2 should stay together -> used in MD_clock */
  115.     p4_global->reference_time = 0; 
  116.     p4_global->reference_time = MD_clock();
  117.  
  118. #if defined(FX2800_SWITCH)
  119.     sw_attach(p4_global->application_id);
  120. #endif
  121. }                /* MD_initenv */
  122.  
  123. /* MD_malloc_hint variables.  Needs to be initialized appropriately
  124.    for each system. */
  125.  
  126. #if defined(TC_2000)
  127.  
  128. static int characteristic = HEAP_INTERLEAVED | HEAP_UNCACHED,    /* "flag" arg to
  129.                                  * heapmalloc(3) */
  130.   locality = HEAP_ANYWHERE;    /* "node" arg to heapmalloc(3) */
  131. #endif
  132.  
  133. P4VOID MD_malloc_hint(a, b)
  134. int a, b;
  135. {
  136. #if defined(TC_2000)
  137.     characteristic = a;
  138.     locality = b;
  139.     if (a == -1)
  140.     xx_malloc(2, b);    /* setting mapped filename */
  141.     else if (a == -2)
  142.     xx_malloc(3, 0);    /* doing heapsync() */
  143. #endif
  144. }
  145.  
  146. char *MD_shmalloc(size)
  147. int size;
  148. {
  149.     char *p;
  150.  
  151. #if defined(BALANCE) || defined(SYMMETRY) || defined(SYMMETRY_PTX)
  152.     p = shmalloc(size);
  153. #else
  154.  
  155. #if defined(GP_1000) || defined(TC_2000)
  156. /*   size = (size | 0xff) + 1;     $$$ Why?  Nuked for now...  -jb */
  157.     p = xx_malloc(1, size);
  158. #  ifdef MALLOC_STATS
  159.       allocated += size;
  160. #  endif
  161. #else
  162.  
  163. #if defined(KSR) && defined(USE_XX_SHMALLOC)
  164.     p = xx_shmalloc((unsigned) size);
  165. #else
  166.  
  167. #if defined(ALLIANT) && defined(USE_XX_SHMALLOC)
  168.     p = xx_shmalloc((unsigned) size);
  169. #else
  170. #if defined(ALLIANT) && !defined(USE_XX_SHMALLOC)
  171.     p = xx_malloc(1, size);
  172. #else
  173.  
  174. #if defined(MULTIMAX)
  175.     p = share_malloc(size);
  176. #else
  177.  
  178. #if defined(SYSV_IPC) && defined(USE_XX_SHMALLOC)
  179.     p = xx_shmalloc((unsigned) size);
  180. #else
  181.  
  182.     p = (char *) p4_malloc(size);
  183. #endif
  184. #endif
  185. #endif
  186. #endif
  187. #endif
  188. #endif
  189. #endif
  190.  
  191.     return (p);
  192. }
  193.  
  194. P4VOID MD_shfree(ptr)
  195. char *ptr;
  196. {
  197.  
  198. #if defined(BALANCE) || defined(SYMMETRY) || defined(SYMMETRY_PTX)
  199.     shfree(ptr);
  200. #else
  201.  
  202. #if defined(TC_2000)
  203.     heapfree(ptr);
  204. #else
  205.  
  206. #if defined(GP_1000)
  207.     p4_dprintf("OOPS: MD_shfree not implemented on bfly1\n");
  208. #else
  209.  
  210. #if defined(KSR) && defined(USE_XX_SHMALLOC)
  211.     xx_shfree(ptr);
  212. #else
  213.  
  214. #if defined(ALLIANT) && defined(USE_XX_SHMALLOC)
  215.     xx_shfree(ptr);
  216. #else
  217. #if defined(ALLIANT) && !defined(USE_XX_SHMALLOC)
  218.     p4_dprintf("OOPS: MD_shfree not yet implemented on alliant\n");
  219. #else    /* ALLIANT */
  220.  
  221. #if defined(MULTIMAX)
  222.     share_free(ptr);
  223. #else
  224.  
  225. #if defined(SYSV_IPC) && defined(USE_XX_SHMALLOC)
  226.     xx_shfree(ptr);
  227. #else
  228.  
  229.     p4_free(ptr);
  230.  
  231. #endif
  232. #endif
  233. #endif
  234. #endif
  235. #endif
  236. #endif
  237. #endif
  238. #endif
  239.  
  240. }
  241.  
  242.  
  243. #if defined(GP_1000)
  244.  
  245. P4BOOL simple_lock(lock)
  246. int *lock;
  247. {
  248.     register short got_lock = 0;
  249.  
  250.     while(!got_lock) 
  251.     {
  252.     while(*lock != 0) /* wait till clear */
  253.         waitspin(7); /* wait 70 microsecs - atomic ops take about 60 */
  254.     if (atomior32(lock, 1) == 0)
  255.         got_lock = 1;
  256.     }
  257.     return(TRUE);
  258. }
  259.  
  260. #define wait_factor 13.0                /* appx 10 microseconds */
  261. P4VOID waitspin(n)
  262. register int n;
  263. {
  264.     n = (int) ((double) n * wait_factor);      /* set wait time */
  265.     while (n > 0)
  266.         n--;
  267. }
  268.  
  269. P4BOOL simple_unlock(lock)
  270. int *lock;
  271. {
  272.     atomand32(lock, 0);
  273.     return(TRUE);
  274. }
  275.  
  276. #endif
  277.  
  278.  
  279. #if defined(TC_2000)
  280.  
  281. /*
  282.  * simple_lock()
  283.  * This function spins on a "semaphore" (lock location).
  284.  * It spins until we get the requested semaphore.  
  285.  */
  286. P4BOOL simple_lock(lock)
  287. int *lock;
  288. {
  289.     register short got_lock = 0;
  290.     while (!got_lock)
  291.     {
  292.     while (*lock != 0)    /* wait till clear */
  293.         /* wait 70 microsecs - atomic ops take about 60 */
  294.         waitspin(7);
  295.     /*
  296.      * someone else may grab lock before we can - be sure to check what
  297.      * the atomic op says WAS there
  298.      */
  299.     if (xmemi(lock, 1) == 0)
  300.         got_lock = 1;
  301.     }
  302.     return (TRUE);
  303. }
  304.  
  305. #define wait_factor 13.0    /* appx 10 microseconds */
  306. P4VOID waitspin(n)
  307. register int n;
  308. {
  309.     n = (int) ((double) n * wait_factor);    /* set wait time */
  310.     while (n > 0)
  311.     n--;
  312. }
  313.  
  314. /*
  315.  * simple_unlock()
  316.  * This function releases the designated semaphore in the set.
  317.  * It is called after a process leaves its critical section.
  318.  */
  319. P4BOOL simple_unlock(lock)
  320. int *lock;
  321. {
  322.     *lock = 0;
  323.     return (TRUE);
  324. }
  325.  
  326. #endif
  327.  
  328.  
  329. #if defined(ALLIANT) && !defined(USE_XX_SHMALLOC)
  330. /*
  331.  * xx_malloc is a memory allocation routine.  It is called in three ways: if typ
  332.  * == 0, then n is the number of bytes to claim as globally-shared memory
  333.  * (from which routines can ask for shared memory).  In this case the routine
  334.  * returns the address of the allocated block (NULL, if an allocation failure
  335.  * occurs).
  336.  *
  337.  * else if typ == 1, then n is taken to be the amount of shared memory
  338.  * requested.  In this case, the routine returns the address of a block of at
  339.  * least n charecters in length.
  340.  *
  341.  * else if typ == 2, then the routine is being asked to return the address of
  342.  * the globally- shared block of memory.
  343.  *
  344.  * The view of shared memory supported by xx_malloc is that a single massive chunk
  345.  * of memory is acquired and handed out by xx_malloc calls with 1 as first
  346.  * argument.
  347.  */
  348.  
  349. struct mem_blk
  350. {
  351.     char *next;
  352.     int l_mem;
  353.     MD_lock_t MEM;
  354.     int pad;            /* pad out to 8-byte boundary */
  355. };
  356.  
  357. char *xx_malloc(typ, n)
  358. int typ, n;
  359. {
  360.     static struct mem_blk *glob_mem = (struct mem_blk *) NULL;
  361.     static int l_mem = 0;
  362.     char *rc;
  363.     int i;
  364.     char *c;
  365.     /* alliant stuff */
  366.     long id;
  367.     /* end alliant stuff */
  368.  
  369.     switch (typ)
  370.     {
  371.       case 0:            /* initialize */
  372.     /* pad & malloc */
  373.  
  374.     /* round to mult of pg size before allocing on page boundary */
  375.     n = ((n + 4095) / 4096) * 4096;
  376.  
  377.     if ((glob_mem = (struct mem_blk *) valloc((long) n)) == NULL)
  378.         p4_error("xx_malloc: failed in valloc", n);
  379.  
  380.     id = (long) getpid();    /* get a unique id */
  381.  
  382.     if (create_shared_region(id, (char *) glob_mem, (long) n, 0))
  383.         p4_error("xx_malloc: failed in create_shared_region", n);
  384.  
  385.     glob_mem->next = (char *) (glob_mem + sizeof(struct mem_blk));
  386.     glob_mem->l_mem = n;
  387.     rc = glob_mem->next;
  388.     MD_lock_init(&glob_mem->MEM);
  389.     break;
  390.  
  391.       case 1:
  392.     i = (n + 7) & (~007);
  393.     MD_lock(&glob_mem->MEM);
  394.     if (glob_mem->l_mem < i)
  395.     {
  396.         p4_dprintf("*** global allocation failure ***\n");
  397.         p4_dprintf("*** attempted %d bytes, %d left\n",
  398.                i, glob_mem->l_mem);
  399.         rc = NULL;
  400.         MD_unlock(&glob_mem->MEM);
  401.         p4_error("xx_malloc: global alloc failed", i);
  402.     }
  403.     else
  404.     {
  405.         rc = glob_mem->next;
  406.         glob_mem->next += i;
  407.         glob_mem->l_mem -= i;
  408.         /*
  409.          * B printf("allocated %d bytes of shared memory\n",i);
  410.          * printf("at %x\n",rc); E
  411.          */
  412.     }
  413.     MD_unlock(&glob_mem->MEM);
  414.     break;
  415.  
  416.       case 2:
  417.     rc = (char *) glob_mem;
  418.     break;
  419.  
  420.       default:
  421.     printf("*** illegal call to xx_malloc *** typ=%d\n", typ);
  422.     }
  423.     return (rc);
  424. }
  425.  
  426. #endif    /* ALLIANT */
  427.  
  428. #ifdef GP_1000
  429. /*
  430.  * xx_malloc is a memory allocation routine.  It is called in three ways: if typ
  431.  * == 0, then n is the number of bytes to claim as globally-shared memory
  432.  * (from which routines can ask for shared memory).  In this case the routine
  433.  * returns the address of the allocated block (NULL, if an allocation failure
  434.  * occurs).
  435.  *
  436.  * else if typ == 1, then n is taken to be the amount of shared memory
  437.  * requested.  In this case, the routine returns the address of a block of at
  438.  * least n charecters in length.
  439.  *
  440.  * else if typ == 2, then the routine is being asked to return the address of
  441.  * the globally- shared block of memory.
  442.  *
  443.  * The view of shared memory supported by xx_malloc is that a single massive chunk
  444.  * of memory is acquired and handed out by xx_malloc calls with 1 as first
  445.  * argument.
  446.  */
  447.  
  448. struct mem_blk
  449. {
  450.     char *next;
  451.     int l_mem;
  452.     MD_lock_t MEM;
  453.     int pad;            /* pad out to 8-byte boundary */
  454. };
  455.  
  456. char *xx_malloc(typ, n)
  457. int typ, n;
  458. {
  459.     static struct mem_blk *glob_mem = (struct mem_blk *) NULL;
  460.     static int l_mem = 0;
  461.     char *rc;
  462.     int i;
  463.     char *c;
  464.     /* bbn stuff */
  465. #define SHMEM_BASE 0x401000
  466.     vm_address_t shmem_seg;
  467.     union cluster_status cl_stat;
  468.     int clus_size;
  469.     int blk_cnt, ok;
  470.     /* end bbn stuff */
  471.  
  472.     switch (typ)
  473.     {
  474.       case 0:            /* initialize */
  475.     /* pad & malloc */
  476.  
  477.     /*
  478.      * printf("clus_size = %d, &clus_size = %d\n",clus_size,&clus_size);
  479.      */
  480.     cluster_stat(HOME_CLUSTER, GET_NODE_LIST, &cl_stat, &clus_size);
  481.     /*
  482.      * printf("clus_size = %d, &clus_size = %d\n",clus_size,&clus_size);
  483.      */
  484.  
  485.     blk_cnt = ((n / clus_size) / vm_page_size) + 1;
  486.  
  487.     /* printf("n = %d,page size = %d  ",n,vm_page_size); */
  488.     /*
  489.      * printf("clus_size = %d, blk_cnt = %d\n", clus_size,blk_cnt);
  490.      */
  491.  
  492.     ok = 1;
  493.     for (i = 0; (i < clus_size) && ok; i++)
  494.     {
  495.         shmem_seg = SHMEM_BASE + (vm_page_size * blk_cnt) * i;
  496.         if (vm_allocate_and_bind(task_self(), &shmem_seg, blk_cnt * vm_page_size,
  497.                      FALSE, i) != KERN_SUCCESS)
  498.         {
  499.         printf("vm_allocate_and_bind failed\n");
  500.         ok = 0;
  501.         }
  502.         else if (vm_inherit(task_self(), shmem_seg, blk_cnt * vm_page_size,
  503.                 VM_INHERIT_SHARE) != KERN_SUCCESS)
  504.         {
  505.         printf("vm_inherit failed\n");
  506.         ok = 0;
  507.         }
  508.     }
  509.  
  510.     if (ok)
  511.     {            /* everything succeeded */
  512.         glob_mem = (struct mem_blk *) SHMEM_BASE;
  513.         glob_mem->next = (char *) (SHMEM_BASE + sizeof(struct mem_blk));
  514.         glob_mem->l_mem = n;
  515.         rc = glob_mem->next;
  516.         MD_lock_init(&glob_mem->MEM);
  517.     }
  518.     break;
  519.  
  520.       case 1:
  521.     i = (n + 7) & (~007);
  522.     MD_lock(&glob_mem->MEM);
  523.     if (glob_mem->l_mem < i)
  524.     {
  525.         p4_dprintf("*** global allocation failure ***\n");
  526.         p4_dprintf("*** attempted %d bytes, %d left\n",
  527.                i, glob_mem->l_mem);
  528.         rc = NULL;
  529.         MD_unlock(&glob_mem->MEM);
  530.         p4_error("xx_malloc: global alloc failed", i);
  531.     }
  532.     else
  533.     {
  534.         rc = glob_mem->next;
  535.         glob_mem->next += i;
  536.         glob_mem->l_mem -= i;
  537.         /* printf("allocated %d bytes of shared memory at %x\n",i,rc); */
  538.     }
  539.     MD_unlock(&glob_mem->MEM);
  540.     break;
  541.  
  542.       case 2:
  543.     rc = (char *) glob_mem;
  544.     break;
  545.  
  546.       default:
  547.     printf("*** illegal call to xx_malloc *** typ=%d\n", typ);
  548.     }
  549.     return (rc);
  550. }
  551.  
  552. #endif
  553.  
  554. #if defined(TC_2000)
  555.  
  556. /*
  557.  * xx_malloc is a memory allocation routine.  It is called in two ways:
  558.  * if typ == 1, then n is taken to be the amount of shared memory
  559.  * requested.  In this case, the routine returns the address of a block of at
  560.  * least n charecters in length.  We round up to cache-line size, since we
  561.  * may have specified cache attributes....
  562.  *
  563.  * else if typ == 2, then n is interpreted as a character pointer, pointing to
  564.  * a string containing a filename that is used for rendesvous as a
  565.  * memory-mapped-file, thus allowing unrelated processes to allocate shared
  566.  * memory with each other.
  567.  *
  568.  * else if typ == 3, then heapsync() is called to help processes avoid doing
  569.  * shared memory map-ins at reference time.
  570.  *
  571.  */
  572.  
  573. char *xx_malloc(typ, n)
  574. int typ, n;
  575. {
  576.     char *mem_ptr, *mapped_filename;
  577.     int alloc_chunk;
  578.  
  579.     switch (typ)
  580.     {
  581.  
  582.       case 1:
  583.     /* pad to multiple of cache-line size */
  584.     alloc_chunk = (n + 17) & (~017);
  585.     /*
  586.      * B printf("allocated %d bytes of shared memory\n",i); printf("at
  587.      * %x\n",mem_ptr); E
  588.      */
  589.     /* gag - refer to our global at the top of the file */
  590.     if ((mem_ptr = heapmalloc(characteristic, locality, alloc_chunk)) == NULL)
  591.         p4_dprintf("*** global allocation failure - general ***\n");
  592.     /* reset hints to "defaults" */
  593.     characteristic = HEAP_INTERLEAVED;
  594.     locality = HEAP_ANYWHERE;    /* $$$ should be HEAP_SCATTERED */
  595.     break;
  596.  
  597.       case 2:
  598.     heapfile((char *) n);
  599.     break;
  600.  
  601.       case 3:
  602.     heapsync();
  603.     break;
  604.  
  605.       default:
  606.     printf("*** illegal call to xx_malloc *** typ=%d\n", typ);
  607.     }
  608.     return (mem_ptr);
  609. }
  610. #endif
  611.  
  612.  
  613. #if defined(IPSC860)
  614.  
  615. struct p4_msg *MD_i860_recv()
  616. /* Low level ipsc 860 message receive routine.
  617.  *
  618.  * All messages should be of the p4_msg type.
  619.  *
  620.  * Blocks until it receives a message.
  621.  *
  622.  * If the type is "ACK_REQUEST", then send back and "ACK_REPLY", to
  623.  * confirm that the message was received.  If the message is of this
  624.  * type, than it is sent in the struct tmsg form, to encapsulate the
  625.  * user's chosen type of message, which gets ignored in this routine.
  626.  */
  627. {
  628.     long type;
  629.     int proc = NODE_PID, node, alloc_size, msg_size;
  630.     struct p4_msg *m;        /* WARNING: deallocate above  */
  631.     char ack = 'a';
  632.  
  633.     /*
  634.      * Probe to see how big the incoming message is.  Block until that
  635.      * message comes in.  Allocate it, and receive it.  All the p4_msg
  636.      * information should automatically, since the message is a p4_msg type.
  637.      */
  638.     p4_dprintfl(20, "receiving a msg via i860 crecv\n");
  639.     cprobe(ANY_P4TYPE_IPSC);
  640.     alloc_size = (int) infocount();
  641.     type = (int) infotype();
  642.     node = (int) infonode();
  643.     msg_size = alloc_size - sizeof(struct p4_msg) + sizeof(char *);
  644.     m = alloc_p4_msg(msg_size);
  645.     crecv(ANY_P4TYPE_IPSC, (char *) m, (long) alloc_size);
  646.     p4_dprintfl(10, "received msg via i860 crecv from=%d type=%d \n",m->from,m->type);
  647.  
  648.     /*
  649.      * If the type is "ACK_REQUEST", fire off the reply. If sender was the
  650.      * host, send it to the procid of the host.
  651.      */
  652.     if (type == ACK_REQUEST_IPSC)
  653.     {
  654.     p4_dprintfl(30, "sending ack to %d\n", m->from);
  655.     csend(ACK_REPLY_IPSC, &ack, sizeof(char), node, proc);
  656.     p4_dprintfl(30, "sent ack to %d\n", m->from);
  657.     }
  658.     return (m);
  659. }
  660.  
  661.  
  662. int MD_i860_send(m)
  663. struct p4_msg *m;
  664. /*
  665.  * Send the message, nonblocking, no wait for acknowledgement of receipt.
  666.  */
  667. {
  668.     int proc = NODE_PID, to;
  669.     char buf;            /* buffer for the ack message */
  670.     int len;
  671.  
  672.     to = p4_local->conntab[m->to].port;
  673.  
  674.     p4_dprintfl(20, "sending msg of type %d from %d to %d via i860 send\n",m->type,m->from,m->to);
  675.     len = m->len + sizeof(struct p4_msg) - sizeof(char *);
  676.     if (!(m->ack_req & P4_ACK_REQ_MASK))
  677.     {
  678.     m->msg_id = (int) isend((long) NO_TYPE_IPSC, m, (long) len, (long) to, (long) proc);
  679.     (p4_global->cube_msgs_out)++;
  680.     p4_dprintfl(10, "sent msg of type %d from %d to %d via i860 isend\n",m->type,m->from,m->to);
  681.     }
  682.     else
  683.     {
  684.     /* Send a message, asking for an acknowledgement of receipt. */
  685.     csend((long) ACK_REQUEST_IPSC, m, (long) len, (long) to, (long) proc);
  686.     m->msg_id = -1;        /* already waited for by csend */
  687.     /* Wait for the acknowledgement. */
  688.     p4_dprintfl(30, "waiting for ack from %d\n", m->to);
  689.     crecv((long) ACK_REPLY_IPSC, &buf, (long) sizeof(char));
  690.     p4_dprintfl(30, "received ack from %d\n", m->to);
  691.     p4_dprintfl(10, "sent msg of type %d from %d to %d via i860 csend\n",m->type,m->from,m->to);
  692.     }
  693. }
  694.  
  695. P4BOOL MD_i860_msgs_available()
  696. {
  697.     P4BOOL rc;
  698.  
  699.     rc = (P4BOOL) iprobe(ANY_P4TYPE_IPSC);
  700.     return (rc);
  701. }
  702.  
  703.  
  704. /* endif for ipsc860 */
  705. #endif
  706.  
  707.  
  708.  
  709. #if defined(CM5)
  710.  
  711. struct p4_msg *MD_CM5_recv()
  712. /* Low level CM-5 message receive routine.
  713.  *
  714.  * All messages should be of the p4_msg type.
  715.  *
  716.  * Blocks until it receives a message.
  717.  *
  718.  * If the type is "ACK_REQUEST", then send back and "ACK_REPLY", to
  719.  * confirm that the message was received.  If the message is of this
  720.  * type, than it is sent in the struct tmsg form, to encapsulate the
  721.  * user's chosen type of message, which gets ignored in this routine.
  722.  */
  723. {
  724.     int type, node, alloc_size, msg_size;
  725.     struct p4_msg *m;        /* WARNING: deallocate above  */
  726.     char ack = 'a';
  727.  
  728.     /*
  729.      * Probe to see how big the incoming message is.  Block until that
  730.      * message comes in.  Allocate it, and receive it.  All the p4_msg
  731.      * information should automatically, since the message is a p4_msg type.
  732.      */
  733.     p4_dprintfl(20, "receiving a msg via cm-5 recv\n");
  734.     CMMD_msg_pending(CMMD_ANY_NODE, CMMD_ANY_TAG);
  735.     alloc_size = CMMD_bytes_received();
  736.     type = CMMD_msg_tag();
  737.     node = CMMD_msg_sender();
  738.     msg_size = alloc_size - sizeof(struct p4_msg) + sizeof(char *);
  739.     m = alloc_p4_msg(msg_size);
  740.     CMMD_receive(node, type, (void *) m, alloc_size);
  741.     p4_dprintfl(10, "received msg via cm-5 recv from=%d type=%d \n",m->from,m->type);
  742.  
  743.     if (type == ACK_REQUEST_CM5)
  744.     {
  745.     p4_dprintfl(30, "sending ack to %d\n", m->from);
  746.     CMMD_send_noblock(m->from,ACK_REPLY_CM5,&ack,sizeof(char));
  747.     p4_dprintfl(30, "sent ack to %d\n", m->from);
  748.     }
  749.     return (m);
  750. }
  751.  
  752.  
  753. int MD_CM5_send(m)
  754. struct p4_msg *m;
  755. {
  756.     int to,len;
  757.     char buf;            /* buffer for the ack message */
  758.  
  759.     to = p4_local->conntab[m->to].port;
  760.  
  761.     p4_dprintfl(20, "sending msg of type %d from %d to %d via cm5 send\n",m->type,m->from,m->to);
  762.     len = m->len + sizeof(struct p4_msg) - sizeof(char *);
  763.     if (!(m->ack_req & P4_ACK_REQ_MASK))
  764.     {
  765.     CMMD_send_noblock(to, NO_TYPE_CM5, (void *) m, len);
  766.     p4_dprintfl(10, "sent msg of type %d from %d to %d via cm5 send\n",m->type,m->from,m->to);
  767.     }
  768.     else
  769.     {
  770.     /* Send a message, asking for an acknowledgement of receipt. */
  771.     CMMD_send_noblock(to, ACK_REQUEST_CM5, (void *) m, len);
  772.     /* Wait for the acknowledgement. */
  773.     p4_dprintfl(30, "waiting for ack from %d\n", m->to);
  774.         CMMD_receive(to, ACK_REPLY_CM5, (void *) &buf, sizeof(char));
  775.     p4_dprintfl(30, "received ack from %d\n", m->to);
  776.     p4_dprintfl(10, "sent msg of type %d from %d to %d via cm5 csend\n",m->type,m->from,m->to);
  777.     }
  778. }
  779.  
  780. P4BOOL MD_CM5_msgs_available()
  781. {
  782.     P4BOOL rc;
  783.  
  784.     rc = CMMD_msg_pending(CMMD_ANY_NODE,CMMD_ANY_TAG);
  785.     return (rc);
  786. }
  787.  
  788. /* endif for cm5 */
  789. #endif
  790.  
  791.  
  792. #if defined(IPSC860)  ||  defined(CM5)
  793.  
  794. #if defined(IPSC860)
  795. #define MYNODE mynode
  796. #endif
  797. #if defined(CM5)
  798. #define MYNODE CMMD_self_address
  799. #endif
  800.  
  801.  
  802. int ns_start(argc, argv)
  803. int *argc;
  804. char **argv;
  805. {
  806.     char *s;
  807.     char ns_host[100];
  808.     struct bm_rm_msg bm_msg;
  809.  
  810.     sprintf(whoami, "ns_%d_%d", MYNODE(), getpid());
  811.  
  812.     /* Send off my info to my rm for forwarding to bm */
  813.     bm_msg.type = p4_i_to_n(REMOTE_SLAVE_INFO);
  814.     bm_msg.slave_idx = p4_i_to_n(MYNODE());
  815.     bm_msg.slave_pid = p4_i_to_n(getpid());
  816.     bm_msg.switch_port = p4_i_to_n(-1);
  817.     ns_host[0] = '\0';
  818.     get_qualified_hostname(ns_host);
  819.     strcpy(bm_msg.host_name,ns_host);
  820.  
  821. #   if defined(IPSC860)
  822.     crecv(SYNC_MSG, &bm_msg, (long) sizeof(struct bm_rm_msg));
  823.     csend((long) INITIAL_INFO, &bm_msg, (long) sizeof(struct bm_rm_msg), (long) 0, (long) NODE_PID);
  824.     crecv(INITIAL_INFO, &bm_msg, (long) sizeof(struct bm_rm_msg));
  825. #   endif 
  826. #   if defined(CM5)
  827.     CMMD_receive(CMMD_ANY_NODE, CMMD_ANY_TAG, (void *) &bm_msg, sizeof(struct bm_rm_msg));
  828.     if (CMMD_msg_tag() != SYNC_MSG)
  829.         exit(0);
  830.     CMMD_send_noblock(0, INITIAL_INFO, &bm_msg, sizeof(struct bm_rm_msg));
  831.     CMMD_receive(CMMD_ANY_NODE, INITIAL_INFO, (void *) &bm_msg, sizeof(struct bm_rm_msg));
  832. #   endif 
  833.  
  834.     if (strcmp(bm_msg.version,p4_version()) != 0)
  835.     {
  836.     p4_dprintf("my version is %s\n",p4_version());
  837.     p4_error("version does not match master \n",0);
  838.     }
  839.     if ((s = (char *) rindex(bm_msg.pgm,'/'))  ==  NULL)
  840.     {
  841.     p4_dprintf("my fullpathname is invalid: %s\n",bm_msg.pgm);
  842.     p4_error("fullpathname is invalid \n",0);
  843.     }
  844.     else
  845.     {
  846.     *s = '\0';  /* chg to directory name only */
  847.     chdir(bm_msg.pgm);
  848.     }
  849.     globmemsize = p4_n_to_i(bm_msg.memsize);
  850.     logging_flag = p4_n_to_i(bm_msg.logging_flag);
  851.     if (logging_flag)
  852.     ALOG_ENABLE;
  853.     else
  854.     ALOG_DISABLE;
  855.  
  856.     MD_initmem(globmemsize);
  857.     alloc_global();  /* sets p4_global */
  858.     p4_local = alloc_local_rm();
  859.     p4_global->num_in_proctable = p4_n_to_i(bm_msg.numinproctab);
  860.     p4_global->local_slave_count = p4_n_to_i(bm_msg.numslaves);
  861.     debug_level = p4_n_to_i(bm_msg.debug_level);
  862.     strcpy(p4_global->application_id, bm_msg.application_id);
  863.  
  864. #   if defined(IPSC860)
  865.     crecv(INITIAL_INFO, p4_global->proctable, (long) sizeof(p4_global->proctable));
  866. #   endif 
  867. #   if defined(CM5)
  868.     CMMD_receive(CMMD_ANY_NODE, INITIAL_INFO, (void *) p4_global->proctable, sizeof(p4_global->proctable));
  869. #   endif 
  870.  
  871.     p4_local = alloc_local_slave();
  872.     p4_local->listener_fd = -1;
  873.     p4_local->my_id = p4_get_my_id_from_proc();
  874.     sprintf(whoami, "p%d_%d", p4_get_my_id(), getpid());
  875.  
  876.     setup_conntab();
  877.  
  878.     usc_init();
  879.     ALOG_SETUP(p4_local->my_id,ALOG_TRUNCATE);
  880.     ALOG_LOG(p4_local->my_id,BEGIN_USER,0,"");
  881.  
  882.     slave();
  883.     ALOG_LOG(p4_local->my_id,END_USER,0,"");
  884.     ALOG_OUTPUT;
  885.     exit(0);
  886. }
  887.  
  888. /* endif for ifdef ipsc860 or cm5 */
  889. #endif 
  890.  
  891.  
  892. int MD_clock()
  893. {
  894.     int i;
  895.  
  896. #if defined(SYMMETRY_PTX)
  897.     time_t t;
  898.  
  899.     time(&t);
  900.     i = (int) (t - p4_global->reference_time);
  901.     i = i * 1000;
  902. #endif
  903.  
  904. #if defined(SUN)   || defined(RS6000)     || defined(DEC5000) \
  905.  || defined(NEXT)  || defined(KSR)        || defined(CM5)     \
  906.  || defined(SYMMETRY) || defined(BALANCE)                     \
  907.  || defined(GP_1000)  || defined(TC_2000) || defined(CRAY)    \
  908.  || defined(TITAN)    || defined(ALLIANT) || defined(SGI)     \
  909.  || defined(MULTIMAX) || defined(IBM3090) || defined(HP)
  910.     struct timeval tp;
  911.     struct timezone tzp;
  912.  
  913.     gettimeofday(&tp, &tzp);
  914.     i = (int) (tp.tv_sec - p4_global->reference_time);
  915.     i *= 1000;
  916.     i += (int) (tp.tv_usec / 1000);
  917. #endif
  918.  
  919. #if defined(IPSC860)
  920.     i = (int) (mclock() - p4_global->reference_time);
  921. #endif
  922.  
  923.     return (i);
  924. }
  925.  
  926. #ifdef DELTA
  927. int myhost()
  928. {
  929.     return (0);
  930. }
  931. #endif
  932.  
  933.  
  934. #ifdef SYSV_IPC
  935.  
  936. int init_sysv_semset(setnum)
  937. int setnum;
  938. {
  939.     int i, semid;
  940. #   if defined(IBM3090) || defined(RS6000) ||    \
  941.        defined(TITAN)  || defined(DEC5000) ||    \
  942.        defined(HP) || defined(KSR)
  943.     int arg;
  944. #   else
  945.     union semun arg;
  946. #   endif
  947.  
  948. #   if defined(IBM3090) || defined(RS6000) ||    \
  949.        defined(TITAN)  || defined(DEC5000) ||    \
  950.        defined(HP) || defined(KSR)
  951.     arg = 1;
  952. #   else
  953.     arg.val = 1;
  954. #   endif
  955.  
  956.     if ((semid = semget(getpid()+setnum,10,IPC_CREAT|0600)) < 0)
  957.     {
  958.     p4_error("semget failed for setnum=%d\n",setnum);
  959.     }
  960.     for (i=0; i < 10; i++)
  961.     {
  962.     if (semctl(semid,i,SETVAL,arg) == -1)
  963.     {
  964.         p4_error("semctl setval failed\n",-1);
  965.     }
  966.     }
  967.     return(semid);
  968. }
  969.  
  970. P4VOID MD_lock_init(L)
  971. MD_lock_t *L;
  972. {
  973. int setnum;
  974.  
  975.     MD_lock(&(p4_global->slave_lock));
  976.     setnum = p4_global->sysv_next_lock / 10;
  977.     if (setnum > P4_MAX_SYSV_SEMIDS)
  978.     {
  979.     p4_error("exceeding max num of p4 semids\n",P4_MAX_SYSV_SEMIDS);
  980.     }
  981.     if (p4_global->sysv_next_lock % 10 == 0)
  982.     {
  983.     p4_global->sysv_semid[setnum] = init_sysv_semset(setnum);
  984.     p4_global->sysv_num_semids++;
  985.     }
  986.     L->semid  = p4_global->sysv_semid[setnum];
  987.     L->semnum = p4_global->sysv_next_lock - (setnum * 10);
  988.     p4_global->sysv_next_lock++;
  989.     MD_unlock(&(p4_global->slave_lock));
  990. }
  991.  
  992.  
  993. P4VOID MD_lock(L)
  994. MD_lock_t *L;
  995. {
  996.     sem_lock[0].sem_num = L->semnum;
  997.     if (semop(L->semid,&sem_lock[0],1) < 0)
  998.     {
  999.         p4_error("OOPS: semop lock failed\n",*L);
  1000.     }
  1001. }
  1002.  
  1003. P4VOID MD_unlock(L)
  1004. MD_lock_t *L;
  1005. {
  1006.     sem_unlock[0].sem_num = L->semnum;
  1007.     if (semop(L->semid,&sem_unlock[0],1) < 0)
  1008.     {
  1009.         p4_error("OOPS: semop unlock failed\n",L);
  1010.     }
  1011. }
  1012. #endif
  1013.  
  1014. #if defined(TCMP)
  1015.  
  1016. P4BOOL MD_tcmp_msgs_available(req_type,req_from)
  1017. int *req_from,*req_type;
  1018. {
  1019.     char *msg = NULL;
  1020.     int len_rcvd;
  1021.     tcmpfunp matcher;
  1022.     tcmp_status tcmpstat;
  1023.  
  1024.     if (*req_type == -1)
  1025.     if (*req_from == -1)
  1026.         matcher = TCMP_MATCH_ANY;
  1027.     else
  1028.         matcher = TCMP_MATCH_SENDER;
  1029.     else if (*req_from == -1)
  1030.     matcher = TCMP_MATCH_TYPE;
  1031.     else
  1032.     matcher = TCMP_MATCH_BOTH;
  1033.     tcmpstat = tcmp_receive(matcher, req_from, req_type,
  1034.                 TCMP_NOBLOCK | TCMP_NOCOPY | TCMP_NODEQUEUE,
  1035.                 &len_rcvd, &msg);
  1036.     if (tcmpstat == TCMP_SUCCESS)
  1037.     return(TRUE);
  1038.     else
  1039.     return(FALSE);
  1040. }
  1041.  
  1042. int MD_tcmp_send(type, from, to, msg, len, data_type, ack_req)
  1043. int type, from, to, len, data_type, ack_req;
  1044. char *msg;
  1045. {
  1046.     int sendflags;
  1047.     tcmp_status tcmpstat;
  1048.  
  1049.     if (ack_req & P4_ACK_REQ_MASK)
  1050.     sendflags = 0;
  1051.     else
  1052.     sendflags = TCMP_NOBLOCK;
  1053.     tcmpstat = tcmp_send(to, type, sendflags, len, msg);
  1054.     if (tcmpstat != TCMP_SUCCESS)
  1055.     p4_error("bad status %d on tcmp_send",tcmpstat);
  1056.     return(0);
  1057. }
  1058.  
  1059. struct p4_msg *MD_tcmp_recv()
  1060. {
  1061.     int type, from, len;
  1062.     struct p4_msg *msg;
  1063.     tcmp_status tcmpstat;
  1064.  
  1065.     tcmpstat = tcmp_receive(TCMP_MATCH_ANY,&from,&type,TCMP_NOCOPY,&len,&msg);
  1066.     if (tcmpstat != TCMP_SUCCESS)
  1067.     p4_error("bad tcmp status %d on receive", tcmpstat);
  1068.  
  1069.     return (msg);
  1070. }
  1071.  
  1072. #endif
  1073.  
  1074. int data_representation(machine_type)
  1075. char *machine_type;
  1076. {
  1077.     if (strcmp(machine_type, "SUN") == 0)             return 1;
  1078.     if (strcmp(machine_type, "HP") == 0)              return 1;
  1079.     if (strcmp(machine_type, "RS6000") == 0)          return 1;
  1080.     if (strcmp(machine_type, "SGI") == 0)             return 1;
  1081.     if (strcmp(machine_type, "NEXT") == 0)            return 1;
  1082.     if (strcmp(machine_type, "CM5") == 0)             return 1;
  1083.     if (strcmp(machine_type, "SYMMETRY") == 0)        return 2;
  1084.     if (strcmp(machine_type, "SYMMETRY_PTX") == 0)    return 2;
  1085.     if (strcmp(machine_type, "SUN386I") == 0)         return 2;
  1086.     if (strcmp(machine_type, "DEC5000") == 0)         return 3;
  1087.     if (strcmp(machine_type, "IBM3090") == 0)         return 4;
  1088.     if (strcmp(machine_type, "TITAN") == 0)           return 5;
  1089.     if (strcmp(machine_type, "FX8") == 0)             return 6;
  1090.     if (strcmp(machine_type, "FX2800") == 0)          return 7;
  1091.     if (strcmp(machine_type, "FX2800_SWITCH") == 0)   return 7;
  1092.     if (strcmp(machine_type, "IPSC860") == 0)         return 8;
  1093.     if (strcmp(machine_type, "IPSC860_SOCKETS") == 0) return 8;
  1094.     if (strcmp(machine_type, "DELTA") == 0)           return 8;
  1095.     if (strcmp(machine_type, "BALANCE") == 0)         return 12;
  1096.     if (strcmp(machine_type, "MULTIMAX") == 0)        return 15;
  1097.     if (strcmp(machine_type, "CRAY") == 0)            return 16;
  1098.     if (strcmp(machine_type, "GP_1000") == 0)         return 17;
  1099.     if (strcmp(machine_type, "TC_2000") == 0)         return 18;
  1100.     if (strcmp(machine_type, "TC_2000_TCMP") == 0)    return 18;
  1101.     if (strcmp(machine_type, "KSR") == 0)             return 19;
  1102. }
  1103.